# 导入socket
import socket
# 导入正则表达式
import re
import time


def send_error(tcp_clinet_socket):
    # 否则返回一个没有找到页面
    response = "HTTP/1.1 404 NOT FOUND\r\n"
    response += "\r\n"
    response += "没有找到该页面"
    tcp_clinet_socket.send(response.encode("gbk"))  # 先发送头部
    # 在异常中需要关闭一下套接字,否则客户端不停的等待访问,这里关闭就变成短连接了
    # tcp_clinet_socket.close()


def getClientMsg(tcp_clinet, msg_data):
    # 解析数据GET /index.html HTTP/1.1
    msg_list = msg_data.splitlines()  # 将数据切割成序列
    ret = re.match(r"[^/]+ (/[^ ]*)", msg_list[0])
    file_name = None
    if ret:
        file_name = ret.group(1)
        if file_name == "/":
            file_name = "/index.html"

        local_file_name = "./html" + file_name

        try:
            f = open(local_file_name, "rb")
        except:
            send_error(tcp_clinet)  # 没有找到页面发送次数据
        else:
            # 发送数据到客户端
            response_body = f.read()
            response_header = "HTTP/1.1 200 OK\r\n"
            # 加了这个头信息，是返回body长度，就不需要在关闭socket.close方法，客户端就知道了
            response_header += "Content-Length:%d\r\n" % len(response_body)
            response_header += "\r\n"

            response = response_header.encode("utf-8") + response_body
            print(response)
            tcp_clinet.send(response)
            f.close()
    else:
        send_error(tcp_clinet)  # 没有找到页面发送次数据


def main():
    # 创建套接字
    tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 绑定ip和端口
    tcp_socket_server.bind(("", 9999))
    # 启动监听
    tcp_socket_server.listen(128)
    # 将套接字改为非阻塞
    tcp_socket_server.setblocking(False)

    # 定义一个序列储存客户端链接套接字
    client_socket_list = list()
    while True:
        time.sleep(1)
        # 等待客户端链接,这里由于获取不到链接所以需要使用异常处理
        try:
            tcp_clinet, addr_clinet = tcp_socket_server.accept()
        except:
            print("没有链接=======")
        else:
            # 获取客户端信息，并返回信息
            client_socket_list.append(tcp_clinet)
            # 如果有客户端链接，将客户端套接字也设置为非阻塞
            tcp_clinet.setblocking(False)

        # 循环所有客户端套接字来接收数据
        for client in client_socket_list:
            try:
                data = client.recv(1024).decode("utf-8")
            except:
                print("没有接收到数据======")
            else:
                if data:
                    getClientMsg(client, data)
                else:
                    # 关闭客户端套接字资源
                    client.close()
                    # 删除套接字
                    client_socket_list.remove(client)
        print(f"list========{len(client_socket_list)}")


if __name__ == "__main__":
    main()
